#ifndef DATA_RECORD_H__
#define DATA_RECORD_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>

enum open_mode_e{
    MODE_ASCII = 0,
    MODE_BIN,
};

#define DR_FILE_NAME_LEN    32
#define DR_INS_NAME_LEN    32

typedef struct data_record_s    *data_record_t;

struct data_record_s{
    int (*dr_open_file)(data_record_t v, const char *file_name);
    int (*dr_open_bin_create)(data_record_t v, const char *file_name);
    int (*dr_open_bin_read)(data_record_t v, const char *file_name);

    void (*record_data)(data_record_t v, const char *fmt, ...);
    void (*record_bin_data)(data_record_t v, const void *ptr, size_t size, size_t nmemb);


    size_t (*read_bin_data)(data_record_t v, void *ptr, size_t size, size_t nmemb);

    int (*dr_close_file)(data_record_t v);



    FILE * fp;
    int open_mode;
    char file_name[DR_FILE_NAME_LEN];
    char ins_name[DR_INS_NAME_LEN];
    bool enable_record;

};

/**
 *@description: 封皮, 少传递this指针, _$ 当做 .
 *@param:
 *@return:
 *@author: Kalimdorsummer
 *@date: 2021-05-14 14:23:18
*/
#define DEFINE_DATA_RECORD_METHOD(name) \
int name##_$dr_open_file(const char *file_name) \
{   \
    return name.dr_open_file(&name, file_name);    \
}   \
int name##_$dr_open_bin_create(const char *file_name) \
{   \
    return name.dr_open_bin_create(&name, file_name);    \
}   \
int name##_$dr_open_bin_read(const char *file_name) \
{   \
    return name.dr_open_bin_read(&name, file_name);    \
}   \
void name##_$record_data(const char *fmt, ...)  \
{   \
    static char buff[64]; \
    memclear(buff, sizeof(buff));  \
    va_list args; \
    va_start(args, fmt);   \
    vsprintf(buff, fmt, args); \
    name.record_data(&name, buff);   \
    va_end(args); \
}   \
void name##_$record_bin_data(const void *ptr, size_t size, size_t nmemb)   \
{   \
    name.record_bin_data(&name, ptr, size, nmemb);  \
}   \
size_t name##_$read_bin_data(void *ptr, size_t size, size_t nmemb)    \
{   \
    return name.read_bin_data(&name, ptr, size, nmemb);    \
}   \
int name##_$dr_close_file(void)  \
{   \
    return name.dr_close_file(&name);  \
}   \

#define DEFINE_DATA_RECORD(name, on_off)    \
struct data_record_s name={ \
    .dr_open_file = dr_open_file,   \
    .dr_open_bin_create = dr_open_bin_create,  \
    .dr_open_bin_read = dr_open_bin_read,   \
    .record_data = record_data, \
    .record_bin_data = record_bin_data, \
    .read_bin_data = read_bin_data, \
    .dr_close_file = dr_close_file, \
    .fp = NULL, \
    .open_mode = MODE_ASCII,    \
    .ins_name = #name,          \
    .enable_record = on_off,    \
};  \
DEFINE_DATA_RECORD_METHOD(name);

int dr_open_file(data_record_t v, const char *file_name);

int dr_open_bin_create(data_record_t v, const char *file_name);
int dr_open_bin_read(data_record_t v, const char *file_name);

void record_data(data_record_t v, const char *fmt, ...);
void record_bin_data(data_record_t v, const void *ptr, size_t size, size_t nmemb);

size_t read_bin_data(data_record_t v, void *ptr, size_t size, size_t nmemb);


int dr_close_file(data_record_t v);

#ifdef __cplusplus
}
#endif

#endif
